using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.AccessControl;
using System.Security.Principal;
using TripleA.Core.Interfaces.Exceptions;

namespace TripleA.Core.Extensions.FileSystem
{
    public class FileIdentityPermissionsStep<T> : FileSystemPermissionStepBase<T>
    {
        private readonly string _filepath;
        private readonly string _identity;
        private readonly AccessControlType _accessType;
        private readonly FileSystemRights _expectedRights;

        public FileIdentityPermissionsStep(string filepath, string identity, AccessControlType accessType, FileSystemRights expectedRights)
        {
            _filepath = filepath;
            _identity = identity;
            _accessType = accessType;
            _expectedRights = expectedRights;
        }

        public override void Execute(T context)
        {
            var ds = File.GetAccessControl(_filepath);
            var rules = ds.GetAccessRules(true, true, typeof(NTAccount)).Cast<FileSystemAccessRule>()
                .Where(rule => string.Compare(rule.IdentityReference.Value, _identity, StringComparison.OrdinalIgnoreCase) == 0)
                .ToList();

            IEnumerable<KeyValuePair<FileSystemRights, bool>> exceptions;

            if (!GetPermissionExceptions(_identity, _accessType, _expectedRights, rules, out exceptions))
                return;

            throw new ExpectationException("Identity '{0}' is missing these '{1}' rights on file '{2}': {3}", 
                _identity, 
                _accessType,
                _filepath, 
                Summarise(exceptions));
        }
    }
}